import datamap
from pygame.locals import *
from minisprite import *
from driver import *
from tools import *

class Tank(DynamicSprite, MovableSprite, VitalSprite, ProducerSprite, CollisionSprite):
    HP = 1
    MAXHP = 3
    HOLD = ((0, 0), (1, 0), (0, 1), (1, 1))
    FRONT = ((0, -1), (-1, 0), (0, 2), (2, 0))
    def __init__(self, node, frame, datamap):
        super(Tank, self).__init__(node, datamap, Tank.HOLD)
        self.dnc_init(frame, PathSignal.UP)
        self.mov_init(self.SPEED)
        self.vtl_init(Tank.HP, Tank.MAXHP)
        self.pdc_init()
        self.col_init()
        self.col_register([Bullet, ], self.pros_bulletcoll)
        self.direct = PathSignal.UP

    def pros_bulletcoll(self, spr):
        if isinstance(spr, Bullet) and spr.parent.__class__ != self.__class__: # there is no KILLSELF
            self.vtl_change(-1)
            if (not self.vtl_alive()) and isinstance(self, Enemy):
                self.datamap.ref_delete(self)
                self.kill()
            
    def fire(self):
        node = (self.node[0] + Tank.FRONT[self.direct][0], self.node[1] + Tank.FRONT[self.direct][1])
        self.driver.send(ProduceSignal( \
                                        30, Bullet, \
                                        (self.datamap.updates, self.datamap.render, self.datamap.bullet), \
                                        node, self.datamap, self.direct))
        
class Player(Tank, KeyboardSprite):
    SPEED = 2
    KBD_DIRECT = [K_UP, K_DOWN, K_LEFT, K_RIGHT]
    KBD_FIRE = [K_SPACE, ]
    def __init__(self, node, datamap):
        rawframe = load_frame('tank.bmp', (8, 8), (0, 0, 0))
        frame = [rawframe[0:2], rawframe[2:4], rawframe[4:6], rawframe[6:8]] # up, left, down, right
        # blending color
        for sub in frame:
            for image in sub:
                blend_color(image, (255, 255, 100))
        super(Player, self).__init__(node, frame, datamap)
        self.kbd_init()
        self.kbd_register(Player.KBD_DIRECT, self.pros_directkey)
        self.kbd_register(Player.KBD_FIRE, self.pros_firekey)

    def pros_directkey(self, key):
        if not self.driver.check(GotoSignal.KIND):
            if key == K_UP:
                self.driver.send(PathSignal(PathSignal.UP, False), True)
            elif key == K_DOWN:
                self.driver.send(PathSignal(PathSignal.DOWN, False), True)
            elif key == K_LEFT:
                self.driver.send(PathSignal(PathSignal.LEFT, False), True)
            elif key == K_RIGHT:
                self.driver.send(PathSignal(PathSignal.RIGHT, False), True)
        self.driver.clear(KeySignal.KIND)
    
    def pros_firekey(self, key):
        if key == K_SPACE: self.fire()            
    
    def update(self):
        # process collision signal
        self.col_collisionsig()
        if self.vtl_alive():
            # process key signal
            self.kbd_keysig()
            # process path signal
            direct = self.mov_pathsig()
            if direct != None: 
                self.direct = direct
                self.dnc_animate(direct) # if processed a new path, turn direct
            # process goto signal
            if self.mov_gotosig(): self.dnc_animate() # if moved ,animate
            # process produce signal
            self.pdc_producesig()
        # super class update
        super(Player, self).update()

class Enemy(Tank, IntelligentSprite):
    SPEED = 1
    def __init__(self, node, datamap, ai, level):
        rawframe = load_frame('tank.bmp', (8, 8), (0, 0, 0))
        frame = [rawframe[32:34], rawframe[34:36], rawframe[36:38], rawframe[38:40]] # up, left, down, right
        # blending color
        for sub in frame:
            for image in sub:
                blend_color(image, (100, 255, 255))
        super(Enemy, self).__init__(node, frame, datamap)
        self.itg_init(ai, level)
    
    def update(self):
        # process collision signal
        self.col_collisionsig()
        if self.vtl_alive():
            # process ai
            self.itg_think()
            # process path signal
            direct = self.mov_pathsig()
            if direct != None:
                self.direct = direct 
                self.dnc_animate(direct) # if processed a new path, turn direct
            # process goto signal
            if self.mov_gotosig(): self.dnc_animate() # if moved ,animate
            # process produce signal
            self.pdc_producesig()
            # super class update        
        super(Enemy, self).update()

class Block(StaticSprite, VitalSprite, CollisionSprite):
    HP = 1
    def __init__(self, node, datamap):
        image = load_image('block.bmp', (0, 0, 0))
        super(Block, self).__init__(node, datamap)
        self.stc_init([image], 0)
        self.vtl_init(Block.HP)
        self.col_init()
        self.col_register([Bullet, ], self.pros_bulletcoll)
        
    def pros_bulletcoll(self, spr):
        if isinstance(spr, Bullet): # there is no KILLSELF
            self.vtl_change(-1)
            if not self.vtl_alive(): 
                self.datamap.ref_delete(self)
                self.kill()
            
    def update(self):
        self.col_collisionsig()
        super(Block, self).update()

class Base(StaticSprite, VitalSprite, CollisionSprite):
    HP = 1
    HOLD = ((0, 0), (1, 0), (0, 1), (1, 1))
    ALIVE = 0
    DEAD = 1   
    def __init__(self, node, datamap):
        imagedict = load_frame('base.bmp', (2, 1), (0, 0, 0))
        super(Base, self).__init__(node, datamap, Base.HOLD)
        self.stc_init(imagedict, Base.ALIVE)
        self.vtl_init(Base.HP)
        self.col_init()
        self.col_register([Bullet, ], self.pros_bulletcoll)
        
    def pros_bulletcoll(self, spr):
        if isinstance(spr, Bullet):
            self.vtl_change(-1)
            if not self.vtl_alive(): self.stc_change(Base.DEAD)
    
    def update(self):
        self.col_collisionsig()
        super(Base, self).update()

class Bullet(StaticSprite, MovableSprite, CollisionSprite):
    SPEED =  4
    HOLD = (
            ((0, 0), (1, 0)),
            ((0, 0), (0, 1)),
            ((0, 0), (1, 0)),
            ((0, 0), (0, 1)),
            )
    def __init__(self, node, map, direct):
        ud = load_frame('bulletUD.bmp', (1, 2), (0, 0, 0))
        lr = load_frame('bulletLR.bmp', (2, 1), (0, 0, 0))
        image = [ud[0], lr[0], ud[1], lr[1]]
        super(Bullet,self).__init__(node, map, Bullet.HOLD[direct])
        self.stc_init(image, direct)
        self.mov_init(Bullet.SPEED)
        # generator path point
        for i in xrange(datamap.DataMap.XAXIS):
            self.driver.send(PathSignal(direct))
        self.col_init()
        self.col_register([None.__class__, Player, Enemy, Block, Base, Bullet], self.pros_allcoll)
        self.direct = PathSignal.UP

    def pros_allcoll(self, spr = None):
        if spr != self.parent: # collided self parent that nothing hapend
            self.datamap.ref_delete(self)
            self.kill()
        
    def update(self):
        self.col_collisionsig()
        if self.alive():
            self.mov_pathsig()        
            self.mov_gotosig()
        
        super(Bullet, self).update()

